﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Configuration;
using log4net;
using System.Web;

namespace Wwtfly.LoggerUtility
{
    public class Log4NetLogger : ILogger
    {
        public Log4NetLogger()
        {
        }

        /// <summary>
        /// info信息
        /// </summary>
        /// <param name="logMessageParams"></param>
        void ILogger.Info(LogMessageParams logMessageParams)
        {
            Logger.LogInfo(logMessageParams.ModuleID, logMessageParams.FuncCode,
                logMessageParams.UserId, logMessageParams.logMessage, logMessageParams.ContextInfo);
        }
        /// <summary>
        /// Debug信息
        /// </summary>
        /// <param name="logMessageParams"></param>
        void ILogger.Debug(LogMessageParams logMessageParams)
        {
            Logger.LogDebug(logMessageParams.ModuleID, logMessageParams.FuncCode,
                logMessageParams.logMessage, logMessageParams.ContextInfo);
        }

        /// <summary>
        /// Error信息
        /// </summary>
        /// <param name="logMessageParams"></param>
        void ILogger.Error(LogMessageParams logMessageParams)
        {
            if (logMessageParams.Excep != null)
            {
                Logger.LogError(logMessageParams.ModuleID, logMessageParams.FuncCode,
                                           logMessageParams.Level, logMessageParams.ErrCode, logMessageParams.Excep, logMessageParams.logMessage, logMessageParams.ContextInfo);

            }
            else
            {
                Logger.LogError(logMessageParams.ModuleID, logMessageParams.FuncCode,
                                         logMessageParams.Level, logMessageParams.ErrCode,
                                         logMessageParams.logMessage, logMessageParams.logMessage, logMessageParams.ContextInfo);

            }
        }

        /// <summary>
        /// Warn信息
        /// </summary>
        /// <param name="logMessageParams"></param>
        public void Warn(LogMessageParams logMessageParams)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Fatal信息
        /// </summary>
        /// <param name="logMessageParams"></param>
        public void Fatal(LogMessageParams logMessageParams)
        {
            throw new NotImplementedException();
        }
    }

    /// <summary>
    /// 类名称：Logger 
    /// 类说明：按照日志的五个级别写日志。日志目录通过配置文件设定
    /// 作者：  
    /// 完成日期：
    /// </summary>
  public class Logger
    {
        private static readonly string loggerPrefix = null;
        private static readonly ILog logdebug = null;
        private static readonly ILog logerror = null;
        private static readonly ILog loginfo = null;
        private static readonly ILog logperf = null;

        static Logger()
        {
            try
            {
                loggerPrefix = ConfigurationManager.AppSettings["LoggerPrefix"];
                if (string.IsNullOrEmpty(loggerPrefix))
                {
                    loggerPrefix = "Logging";
                }
                logdebug = LogManager.GetLogger(loggerPrefix + ".Debug");
                logerror = LogManager.GetLogger(loggerPrefix + ".Error");
                loginfo = LogManager.GetLogger(loggerPrefix + ".Info");
                logperf = LogManager.GetLogger(loggerPrefix + ".Perf");


            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 记录程序正常运行的日志
        /// </summary>
        /// <param name="moduleID">模块编号 （每个BLL类有一个模块编号）</param>
        /// <param name="funcCode">功能编号</param>
        /// <param name="userid">用户编号</param>
        /// <param name="msg">在异常或错误情况下给出的进一步的说明信息</param>
        /// <param name="contextInfo">上下文信息（由调用方生成，以名值对方式组织，如userid=123;username=abc）</param>
        public static void LogInfo(string moduleID, string funcCode, int userid, string msg, string contextInfo)
        {
            StringBuilder logMessage = new StringBuilder();

            logMessage.AppendFormat("Time={0}; ModuleID={1}; FuncCode={2}; UserID={3}; ", DateTime.Now, moduleID, funcCode, userid);

            if (!string.IsNullOrEmpty(contextInfo))
            {
                logMessage.AppendLine();
                logMessage.AppendFormat("[ContextInfo]={0}", contextInfo);
            }

            if (!string.IsNullOrEmpty(msg))
            {
                logMessage.AppendLine();
                logMessage.AppendFormat("[Custom Message]={0}", msg);
            }

            logMessage.AppendLine();

            if (loginfo.IsInfoEnabled) loginfo.Info(logMessage.ToString());
        }

        /// <summary>
        /// 记调试日志
        /// </summary>
        /// <param name="moduleID">模块编号</param>
        /// <param name="funcCode">功能编号</param>
        /// <param name="msg">在异常或错误情况下给出的进一步的说明信息</param>
        /// <param name="contextInfo">上下文信息（由调用方生成，以名值对方式组织，如userid=123;username=abc）</param>
        public static void LogDebug(string moduleID, string funcCode, string msg, string contextInfo)
        {
            StringBuilder logMessage = new StringBuilder();
            logMessage.AppendFormat("Time={0}; ModuleID={1}; FuncCode={2}; ", DateTime.Now, moduleID, funcCode);

            if (!string.IsNullOrEmpty(contextInfo))
            {
                logMessage.AppendLine();
                logMessage.AppendFormat("[ContextInfo]={0}", contextInfo);
            }

            if (!string.IsNullOrEmpty(msg))
            {
                logMessage.AppendLine();
                logMessage.AppendFormat("[Custom Message]={0}", msg);
            }

            logMessage.AppendLine();

            if (logdebug.IsDebugEnabled)
                logdebug.Debug(logMessage.ToString());
        }

        /// <summary>
        /// 记错误日志或异常日志
        /// </summary>
        /// <param name="moduleID">模块编号</param>
        /// <param name="funcCode">功能编号</param>
        /// <param name="level">日志级别，3级（WARN，EROR，FATL）</param>
        /// <param name="errCode">错误码，对于没有明确错误码的场合需要给一个系统级的通用错误码</param>
        /// <param name="ex">发生的异常</param>
        /// <param name="msg">错误信息</param>
        /// <param name="contextInfo">错误上下文</param>
        public static void LogError(string moduleID, string funcCode, AppErrorLevel level, int errCode, Exception ex, string msg, string contextInfo)
        {
            LogError(moduleID, funcCode, level, errCode, BuildExceptionMessage(ex), msg, contextInfo);
        }

        /// <summary>
        /// 记错误日志或异常日志
        /// </summary>
        /// <param name="moduleID">模块编号</param>
        /// <param name="funcCode">功能编号</param>
        /// <param name="level">日志级别，3级（WARN，EROR，FATL）</param>
        /// <param name="errCode">错误码，对于没有明确错误码的场合需要给一个系统级的通用错误码</param>
        /// <param name="ex">发生的异常</param>
        /// <param name="msg">错误信息</param>
        /// <param name="contextInfo">错误上下文</param>
        public static void LogError(string moduleID, string funcCode, AppErrorLevel level, string errCode, Exception ex, string msg, string contextInfo)
        {
            LogError(moduleID, funcCode, level, errCode, BuildExceptionMessage(ex), msg, contextInfo);
        }

        /// <summary>
        /// 记错误日志或异常日志
        /// </summary>
        /// <param name="moduleID">模块编号</param>
        /// <param name="funcCode">功能编号</param>
        /// <param name="level">日志级别，3级（WARN，EROR，FATL）</param>
        /// <param name="errCode">错误码，对于没有明确错误码的场合需要给一个系统级的通用错误码</param>
        /// <param name="ex">发生的异常</param>
        /// <param name="msg">错误信息</param>
        /// <param name="contextInfo">错误上下文</param>
        public static void LogError(string moduleID, string funcCode, AppErrorLevel level, int errCode, string ex, string msg, string contextInfo)
        {
            LogError(moduleID, funcCode, level, errCode.ToString(), ex, msg, contextInfo);
        }

        /// <summary>
        /// 记错误日志或异常日志
        /// </summary>
        /// <param name="moduleID">模块编号</param>
        /// <param name="funcCode">权限代码</param>
        /// <param name="level">日志级别，3级（WARN，EROR，FATL）<</param>
        /// <param name="errCode">错误码，对于没有明确错误码的场合需要给一个系统级的通用错误码</param>
        /// <param name="ex">发生的异常</param>
        /// <param name="msg">错误信息</param>
        /// <param name="contextInfo">错误上下文</param>
        public static void LogError(string moduleID, string funcCode, AppErrorLevel level, string errCode, string ex, string msg, string contextInfo)
        {
            StringBuilder logMessage = new StringBuilder();
            logMessage.AppendFormat("Time={0}; LogLevel={1}; ModuleID={2}; FuncCode={3}; ErrorCode={4}; ", DateTime.Now, level, moduleID, funcCode, errCode);

            if (!string.IsNullOrEmpty(contextInfo))
            {
                logMessage.AppendLine();
                logMessage.AppendFormat("[ContextInfo]={0}", contextInfo);
            }

            if (!string.IsNullOrEmpty(msg))
            {
                logMessage.AppendLine();
                logMessage.AppendFormat("[Custom Message]={0}", msg);
            }

            if (ex != null)
            {
                logMessage.AppendLine();
                logMessage.AppendLine(ex);
                //logMessage.AppendLine(string.Format("Exception={0}", ex));
            }

            if (logerror.IsErrorEnabled) logerror.Error(logMessage.ToString());
        }

        /// <summary>
        /// 记性能日志
        /// </summary>
        /// <param name="startTime">开始时间</param>
        /// <param name="moduleID">模块编号</param>
        /// <param name="funcCode">功能编号</param>
        /// <param name="contextInfo">上下文信息（由调用方生成，以名值对方式组织，如userid=123;username=abc）</param>
        public static void LogPerf(DateTime startTime, string moduleID, string funcCode, string contextInfo)
        {
            DateTime endTime = DateTime.Now;
            TimeSpan ts = endTime.Subtract(startTime);

            StringBuilder logMessage = new StringBuilder();
            logMessage.AppendFormat("StartTime={0}; EndTime={1}; Interval={2}(ms); ModuleID={3}; FuncCode={4}; ", startTime, DateTime.Now, ts.TotalMilliseconds, moduleID, funcCode);

            if (!string.IsNullOrEmpty(contextInfo))
            {
                logMessage.AppendLine();
                logMessage.AppendFormat("[ContextInfo]={0}", contextInfo);
            }

            logMessage.AppendLine();

            if (logperf.IsWarnEnabled) logperf.Warn(logMessage.ToString());
        }

        public static void Log(string logmsg, string loggerName)
        {
            LogManager.GetLogger(loggerName).Info(logmsg);
        }

        public static ILog GetLogger(string loggerName)
        {
            return LogManager.GetLogger(loggerName);
        }

        #region Helper
        private static string BuildExceptionMessage(Exception x)
        {
            Exception logException = x;
            if (x.InnerException != null)
                logException = x.InnerException;

            string strErrorMsg = string.Empty;

            if (HttpContext.Current != null)
            {
                strErrorMsg += "[Error in Path]=" + HttpContext.Current.Request.Path;

                // Get the QueryString along with the Virtual Path
                strErrorMsg += Environment.NewLine + "[Raw Url]=" + HttpContext.Current.Request.RawUrl;
            }

            // Get the error message type
            strErrorMsg += Environment.NewLine + "[Exception Type]=" + logException.GetType().ToString();

            // Get the error message
            strErrorMsg += Environment.NewLine + "[Error Message]=" + logException.Message;

            // Source of the message
            strErrorMsg += Environment.NewLine + "[Source]=" + logException.Source;

            // Stack Trace of the error
            strErrorMsg += Environment.NewLine + "[Stack Trace]=" + logException.StackTrace;

            // Method where the error occurred
            strErrorMsg += Environment.NewLine + "[TargetSite]=" + logException.TargetSite;
            return strErrorMsg;
        }
        #endregion
    }
}
